home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / alias.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  8KB  |  368 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. #include "mutt.h"
  20.  
  21. #include <pwd.h>
  22. #include <string.h>
  23.  
  24. static LIST *AliasList = NULL;
  25.  
  26. static ADDRESS *lookup_alias (const char *s)
  27. {
  28.   ALIAS *t = Aliases;
  29.  
  30.   for (; t; t = t->next)
  31.     if (!strcasecmp (s, t->name))
  32.       return (t->addr);
  33.   return (NULL);   /* no such alias */
  34. }
  35.  
  36. static ADDRESS *mutt_expand_aliases_r (ADDRESS *a)
  37. {
  38.   ADDRESS *head = 0, *last = 0, *t, *w;
  39.   LIST *u;
  40.   char i;
  41.  
  42.   while (a)
  43.   {
  44.     if (a->host && *a->host == '@' && !a->personal)
  45.     {
  46.       t = lookup_alias (a->mailbox);
  47.  
  48.       if (t)
  49.       {    
  50.         i = 0;
  51.         for (u = AliasList; u; u = u->next)
  52.     {
  53.       if (strcmp (a->mailbox, u->data) == 0) /* alias already found */
  54.       {
  55.         dprint (1, (debugfile, "mutt_expand_aliases_r(): loop in alias found for '%s'\n", a->mailbox));
  56.         i = 1;
  57.         break;
  58.       }
  59.     }
  60.  
  61.         if (!i)
  62.     {
  63.           u = safe_malloc (sizeof (LIST));
  64.           u->data = safe_strdup (a->mailbox);
  65.           u->next = AliasList;
  66.           AliasList = u;
  67.       w = rfc822_cpy_adr (t);
  68.       w = mutt_expand_aliases_r (w);
  69.       if (head)
  70.         last->next = w;
  71.       else
  72.         head = last = w;
  73.       while (last && last->next)
  74.         last = last->next;
  75.         }
  76.     t = a;
  77.     a = a->next;
  78.     t->next = NULL;
  79.     mutt_free_address (&t);
  80.     continue;
  81.       }
  82.       else
  83.       {
  84.     struct passwd *pw = getpwnam (a->mailbox);
  85.     char buffer[256], *p;
  86.  
  87.     if (pw)
  88.     {
  89.       strfcpy (buffer, pw->pw_gecos, sizeof (buffer));
  90.       if ((p = strchr (buffer, ',')))
  91.         *p = 0;
  92.       a->personal = safe_strdup (buffer);
  93.     }
  94.       }
  95.     }
  96.  
  97.     if (head)
  98.     {
  99.       last->next = a;
  100.       last = last->next;
  101.     }
  102.     else
  103.       head = last = a;
  104.     a = a->next;
  105.     last->next = NULL;
  106.   }
  107.  
  108.   if (option (OPTUSEDOMAIN))
  109.   {
  110.     /* now qualify all local addresses */
  111.     for (t = head; t; t = t->next)
  112.     {
  113.       if (t->host && *t->host == '@')
  114.       {
  115.     safe_free ((void **) &t->host);
  116.     t->host = safe_strdup (Fqdn);
  117.       }
  118.     }
  119.   }
  120.  
  121.   return (head);
  122. }
  123.  
  124. ADDRESS *mutt_expand_aliases (ADDRESS *a)
  125. {
  126.   ADDRESS *t;
  127.  
  128.   t = mutt_expand_aliases_r (a);
  129.   mutt_free_list (&AliasList);
  130.   return (t);
  131. }
  132.  
  133. /* if someone has an address like
  134.  *    From: Michael `/bin/rm -f ~` Elkins <me@cs.hmc.edu>
  135.  * and the user creates an alias for this, Mutt could wind up executing
  136.  * the backtics because it writes aliases like
  137.  *    alias me Michael `/bin/rm -f ~` Elkins <me@cs.hmc.edu>
  138.  * To avoid this problem, use a backslash (\) to quote any backtics.  We also
  139.  * need to quote backslashes as well, since you could defeat the above by
  140.  * doing
  141.  *    From: Michael \`/bin/rm -f ~\` Elkins <me@cs.hmc.edu>
  142.  * since that would get aliased as
  143.  *    alias me Michael \\`/bin/rm -f ~\\` Elkins <me@cs.hmc.edu>
  144.  * which still gets evaluated because the double backslash is not a quote.
  145.  */
  146. static void write_safe_address (FILE *fp, char *s)
  147. {
  148.   while (*s)
  149.   {
  150.     if (*s == '\\' || *s == '`')
  151.       fputc ('\\', fp);
  152.     fputc (*s, fp);
  153.     s++;
  154.   }
  155. }
  156.  
  157. void mutt_create_alias (ENVELOPE *cur)
  158. {
  159.   ALIAS *new, *t;
  160.   char buf[LONG_STRING];
  161.   char prompt[SHORT_STRING];
  162.   FILE *rc;
  163.   ADDRESS *adr = NULL;
  164.  
  165.   if (cur)
  166.   {
  167.     if (mutt_addr_is_user (cur->from))
  168.     {
  169.       if (cur->to && !mutt_is_mail_list (cur->to))
  170.     adr = cur->to;
  171.       else
  172.     adr = cur->cc;
  173.     }
  174.     else if (cur->reply_to && !mutt_is_mail_list (cur->reply_to))
  175.       adr = cur->reply_to;
  176.     else
  177.       adr = cur->from;
  178.  
  179.   }
  180.  
  181.   if (adr)
  182.     strfcpy (buf, adr->mailbox, sizeof(buf));
  183.   else
  184.     buf[0] = '\0';
  185.   
  186.   if (mutt_get_field ("Alias as: ", buf, sizeof (buf), 0) != 0 || !buf[0])
  187.     return;
  188.  
  189.   /* check to see if the user already has an alias defined */
  190.   if (lookup_alias (buf))
  191.   {
  192.     mutt_error ("You already have an alias defined with that name!");
  193.     return;
  194.   }
  195.  
  196.   new = safe_calloc (1, sizeof (ALIAS));
  197.   new->name = safe_strdup (buf);
  198.  
  199.   if (adr)
  200.     mutt_simple_address (buf, sizeof (buf), adr);
  201.   else
  202.     buf[0] = 0;
  203.  
  204.   if (mutt_get_field ("Address: ", buf, sizeof (buf), 0) != 0 || !buf[0])
  205.   {
  206.     mutt_free_alias (&new);
  207.     return;
  208.   }
  209.   rfc822_parse_adrlist (&new->addr, buf, Fqdn);
  210.  
  211.   if (adr && adr->personal && !mutt_is_mail_list (adr))
  212.     strfcpy (buf, adr->personal, sizeof (buf));
  213.   else
  214.     buf[0] = 0;
  215.  
  216.   if (mutt_get_field ("Personal name: ", buf, sizeof (buf), 0) != 0)
  217.   {
  218.     mutt_free_alias (&new);
  219.     return;
  220.   }
  221.   new->addr->personal = safe_strdup (buf);
  222.  
  223.   buf[0] = 0;
  224.   rfc822_write_address (buf, sizeof (buf), new->addr);
  225.   snprintf (prompt, sizeof (prompt), "[%s = %s] Accept?", new->name, buf);
  226.   if (mutt_yesorno (prompt, 1) != 1)
  227.   {
  228.     mutt_free_alias (&new);
  229.     return;
  230.   }
  231.  
  232.   if ((t = Aliases))
  233.   {
  234.     while (t->next)
  235.       t = t->next;
  236.     t->next = new;
  237.   }
  238.   else
  239.     Aliases = new;
  240.  
  241.   strfcpy (buf, AliasFile, sizeof (buf));
  242.   if (mutt_get_field ("Save to file: ", buf, sizeof (buf), M_FILE) != 0)
  243.     return;
  244.   mutt_expand_path (buf, sizeof (buf));
  245.   if ((rc = fopen (buf, "a")))
  246.   {
  247.     buf[0] = 0;
  248.     rfc822_write_address (buf, sizeof (buf), new->addr);
  249.     fprintf (rc, "alias %s ", new->name);
  250.     write_safe_address (rc, buf);
  251.     fputc ('\n', rc);
  252.     fclose (rc);
  253.     mutt_message ("Alias added.");
  254.   }
  255.   else
  256.     mutt_perror (buf);
  257. }
  258.  
  259. /*
  260.  * This routine looks to see if the user has an alias defined for the given
  261.  * address.
  262.  */
  263. ADDRESS *alias_reverse_lookup (ADDRESS *a)
  264. {
  265.   ALIAS *t = Aliases;
  266.   ADDRESS *ap;
  267.  
  268.   if (!a || !a->mailbox || !a->host)
  269.     return NULL;
  270.  
  271.   while (t)
  272.   {
  273.     /* cycle through all addresses if this is a group alias */
  274.     ap = t->addr;
  275.     while (ap)
  276.     {
  277.       if (ap->mailbox && ap->host &&
  278.       strcasecmp (ap->mailbox, a->mailbox) == 0 &&
  279.       strcasecmp (ap->host, a->host) == 0)
  280.     return ap;
  281.       ap = ap->next;
  282.     }
  283.     t = t->next;
  284.   }
  285.   return 0;
  286. }
  287.  
  288. /* alias_complete() -- alias completion routine
  289.  *
  290.  * given a partial alias, this routine attempts to fill in the alias
  291.  * from the alias list as much as possible
  292.  */
  293. int mutt_alias_complete (char *s, size_t buflen)
  294. {
  295.   ALIAS *a = Aliases;
  296.   ALIAS *a_list = NULL, *a_cur = NULL;
  297.   char bestname[STRING];
  298.   int i;
  299.  
  300.   memset (bestname, 0, sizeof (bestname));
  301.  
  302. #define min(a,b)        ((a<b)?a:b)
  303.  
  304.   while (a)
  305.   {
  306.     if (a->name && strstr (a->name, s) == a->name)
  307.     {
  308.       if (!bestname[0]) /* init */
  309.     strfcpy (bestname, a->name, min (strlen (a->name) + 1, sizeof (bestname)));
  310.       else
  311.       {
  312.     for (i = 0 ; a->name[i] && a->name[i] == bestname[i] ; i++)
  313.       ;
  314.     bestname[i] = 0;
  315.       }
  316.     }
  317.     a = a->next;
  318.   }
  319.  
  320.   if ((bestname[0] == 0) || /* if we didn't find anything */
  321.       (s[0] == 0))          /* or we weren't given anything */
  322.   {
  323.     mutt_alias_menu (s, buflen, Aliases);
  324.     return 0;
  325.   }
  326.   else
  327.   {
  328.     if (strcmp (bestname, s) == 0) /* add anything to the completion? */
  329.     {
  330.       /* build alias list and show it */
  331.       a = Aliases;
  332.       while (a)
  333.       {
  334.     if (a->name && (strstr (a->name, s) == a->name))
  335.     {
  336.       if (!a_list)  /* init */
  337.         a_cur = a_list = (ALIAS *) safe_malloc (sizeof (ALIAS));
  338.       else
  339.       {
  340.         a_cur->next = (ALIAS *) safe_malloc (sizeof (ALIAS));
  341.         a_cur = a_cur->next;
  342.       }
  343.       memcpy (a_cur, a, sizeof (ALIAS));
  344.       a_cur->next = NULL;
  345.     }
  346.     a = a->next;
  347.       }
  348.  
  349.       s[0] = 0; /* reset string before passing to alias_menu */
  350.       mutt_alias_menu (s, buflen, a_list);
  351.  
  352.       /* free the alias list */
  353.       while (a_list)
  354.       {
  355.     a_cur = a_list;
  356.     a_list = a_list->next;
  357.     safe_free ((void **) &a_cur);
  358.       }
  359.  
  360.       return 0;
  361.     }
  362.     else /* we are adding something to the complet